package com.huishu.order.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;

import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName：StockServiceImpl
 * @Author: ljj
 * @Date: 2023/4/13 15:37
 */
@Slf4j
@Service
public class StockServiceImpl {
    /**
     * 库存不足
     */
    public static final int LOW_STOCK = 0;

    /**
     * 不限库存
     */
    public static final long UNINITIALIZED_STOCK = -1L;

    /**
     * key
     */
    public static final String REDIS_KEY = "REDIS_KEY:STOCK:";

    /**
     * Redis 客户端
     */
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 执行扣库存的脚本
     */
    public final static String STOCK_LUA;

    static {
        /**
         *
         * @desc 扣减库存Lua脚本
         *
         * @params 库存key
         * @return
         *      -2:库存不足
         *      -1:库存未初始化
         *      大于等于0:剩余库存（扣减之后剩余的库存）
         *      redis缓存的库存(value)是-1表示不限库存，直接返回1
         */
        String strBuilder = "if (redis.call('exists', KEYS[1]) == 1) then" +
                " local stock = tonumber(redis.call('get', KEYS[1]));" +
                " local num = tonumber(ARGV[1]);" +
                " if (stock == -1) then" +
                " return 1;" +
                " end;" +
                " if (stock >= num) then" +
                " return redis.call('incrby', KEYS[1], 0 - num);" +
                " end;" +
                " return -2;" +
                "end;" +
                "return -1;";
        STOCK_LUA = strBuilder;
    }


    /**
     * 获取库存
     *
     * @param key 库存key
     * @return 0:库存不足; -1:库存未初始化; 大于0:剩余库存
     */
    public int getStock(String key) {
        Integer stock = (Integer) redisTemplate.opsForValue().get(key);
        return stock == null ? -1 : stock;
    }

    /**
     * 扣库存
     *
     * @param key 库存key
     * @return 扣减之前剩余的库存【0:库存不足; -1:库存未初始化; 大于0:扣减之后剩余的库存】
     */
    public Long stock(String key, Integer num) {
        // 脚本里的KEYS参数
        List<String> keys = new ArrayList<>();
        keys.add(key);
        // 脚本里的ARGV参数
        List<String> args = new ArrayList<>();
        args.add(Integer.toString(num));
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(STOCK_LUA, Long.class);
        Long execute = redisTemplate.execute(redisScript, keys, num);
        return execute;
    }
}
